import os

from Config import Config
from activist.GenericData import GenericData

class _DataStore(object):
    """it makes sense for this to be a subclass of dict, but i
    can't get my __getstate__ trick to work; maybe the pickler
    is special-casing dicts...?"""
    
    _path = os.path.join(Config.dataPath,'objects')
    _objs = {}
    _generics = []
    _categories = []
    _chronologicalEvents = None
    _events = []
    _monthlyEvents = {}
    _aliases = []
    _admins = None

    def chronologicalEvents(self):
        from activist.Event import Event
        if not self._chronologicalEvents:
            self._chronologicalEvents = []
            for x in self.values():
                if isinstance(x,Event):
                    self._chronologicalEvents.append(x)

                                        # FIXME
            from activist.web.resource import sortListingsByDate
            self._chronologicalEvents.sort(sortListingsByDate)
        return self._chronologicalEvents

    def clearMonthCache(self):
        self._monthlyEvents.clear()
        
    def getEventsForMonth(self,year,month):
        from activist.Event import ProxyForRecurringEvent
        from activist import Time
        key = (year*100) + month
        if self._monthlyEvents.has_key(key):
            return self._monthlyEvents[key]

        #print "BUILDING events for",year,month
        rtn = []
        for x in self._events:
            if x.info().whenRaw().isValid(year,month,None):
                if not isinstance(x.info().whenRaw(),Time.Repeating):
                    rtn.append(x)
                    continue
                
                m = month
                import time
                day = 0
                while m == month:
                    p = ProxyForRecurringEvent(x,year,month,day)
                    day = p.thisone.tm_mday
                    m = p.thisone.tm_mon
                    if m == month and x.info().whenRaw().isValid(year,month,day):
                        rtn.append(p)
        from activist.web.resource import sortListingsByDate
        rtn.sort(sortListingsByDate)
        rtn.reverse()
        self._monthlyEvents[key] = rtn
        return rtn

    def getAllAdministrators(self):
        """ !mw! FIXME this cache should be cleared sometimes...disabled until that's defined """
        #if self._admins:
        #    return self._admins
        self._admins = []
        from activist.Person import Person
        for x in self._objs.values():
            if isinstance(x,Person):
                if x.isAdministrator():
                    self._admins.append(x)
        return self._admins


    def save(self):
        print "NOT SAVING!"
        import activist.Data
        #self.dumpObjects()
        path = os.path.join(self._path,'last_id')
        file = open(path,'w')
        file.write(str(activist.Data.next_id)+'\n')
        file.close()

    def _dumpXML(self):
        print "\ndumping getXML from all loaded objects:"

        for x in self._objs.values():
            print x.getXML()
            x._test()

    def checkpointSingleXML(self, file):
        for x in self._objs.values():
            file.write( x.getXML() + '\n\n' )

    def __getstate__(self):
        return self.dumpObjects()

    def dumpObjects(self):
        from activist.MetaData import MetaData
        for x in self._objs.values():
            if isinstance(x,MetaData):
                path = os.path.join(self._path,str(x.id()))
                file = open(path+'.metadata','wb')
                file.write( x.getXML() )
                file.close()
            else:
                path = os.path.join(self._path,str(x.id()))
                file = open(path+'.data','wb')
                file.write( x.getXML() )
                file.close()
        return {}

    def aliases(self):
        return self._aliases

    def translatePathViaAliases(self,path):
        for alias in self._aliases:
            x = alias.translate(path)
            if x: return x
        return None

    def getByClass(self,klass):
        for x in self._objs.values():
            if x.__class__ == klass:
                yield x
        return

    def getPlaceByName(self,name):
        import activist.Place
        name = name.lower().strip()
        for x in self.getByClass(activist.Place.Place):
            if x._name.lower().strip() == name:
                return x
        return None

    def keys(self):
        return self._objs.keys()
    def values(self):
        return self._objs.values()
    def has_key(self,id):
        return self._objs.has_key(id)
    def getGenericDataByTitle(self,title):
        from activist.GenericData import GenericData
        for obj in self._generics:
            if obj.title() == title:
                return obj
        return None
    def getCategories(self):
        return self._categories
    def __setitem__(self,key,value):
        raise "Use register instead"
        if self._objs.has_key(key):
            raise "Key already exists! %s" % key
        self._objs[key] = value
    def __getitem__(self,key):
        return self._objs[key]

    def _reregister(self,data,old,new):
        del self._objs[old]
        self._objs[new] = data
    def register(self,data):
        from activist.Category import Category
        from activist.Event import Event
        from activist.Alias import Alias
        from activist.GenericData import GenericData
        if isinstance(data,Event):
            self._chronologicalEvents = None
            self._events.append(data)
            self._monthlyEvents.clear()
        elif isinstance(data,GenericData):
            if not data in self._generics:
                self._generics.append(data)
                ##self._objs[data.title()] = data <-- moved to GenericData
        elif isinstance(data,Category):
            if not data in self._categories:
                self._categories.append(data)
        elif isinstance(data,Alias):
            if not data in self._aliases:
                self._aliases.append(data)
        if self._objs.has_key(data.id()) and self._objs[data.id()] is not data:
            print "cannot add different objects with the same id! " + str(self._objs[data.id()]) + ', ' + data.id() + ', ' + self._objs[data.id()].id()
            print "  new:",data.__class__,"old:",self._objs[data.id()].__class__
            raise "cannot add different objects with the same id! " + str(self._objs[data.id()]) + ' :: ' + str(data) + ' :: ' + data.id() + ', ' + self._objs[data.id()].id()
        self._objs[data.id()] = data
    def remove(self,data):
        data._remove()
        from activist.Event import Event
        from activist.Alias import Alias
        if isinstance(data,Event):
            self._chronologicalEvents = None
            self._monthlyEvents.clear()
            self._events.remove(data)
        if isinstance(data,Alias):
            self._aliases.remove(data)
        #print "   removed",data.id(),"from datastore"
        del self._objs[data.id()]
        
        # !mw! why is this here?
        for meta in data.metadata():
            print "    STILL HAS META:",meta
            #self.remove(meta)

    def __str__(self):
        return '<DataStore: %s>' % self._objs.keys()
    
DataStore = _DataStore()

